/**
 * Author: ling
 * Create Time: 2018-11-28 16:14
 * Description: 单例模式
 */

// 单例实现
/**
 * 通过Singleton.getInstance来获取Singleton类的唯一对象，
 * 这种方式相对简单，但有一个问题，就是增加了这个类的“不透明性”，
 * Singleton类的使用者必须知道这是一个单例类，跟以往通过newXXX的方式来获取对象不同，
 * 这里偏要使用Singleton.getInstance来获取对象
 */
const Singleton = function (name) {
  this.name = name;
  this.instance = null
};
Singleton.prototype.getName = function() {
  return this.name;
};
Singleton.getInstance = function (name) {
  return this.instance || (this.instance = new Singleton(name))
};

// 透明单例
/**
 * 为了把instance封装起来，我们使用了自执行的匿名函数和闭包，
 * 并且让这个匿名函数返回真正的Singleton构造方法，这增加了一些程序的复杂度，阅读起来也不是很舒服。
 */
const CreateDiv = function () {
  let instance;
  /**
   * CreateDiv的构造函数实际上负责了两件事情。
   * 第一是创建对象和执行初始化init方法，第二是保证只有一个对象。
   * 虽然我们目前还没有接触过“单一职责原则”的概念，但可以明确的是，这是一种不好的做法，至少这个构造函数看起来很奇怪。
   * 假设我们要让这个类从单例类变成一个普通的可产生多个实例的类，
   * 那我们必须得改写CreateDiv构造函数，把控制创建唯一对象的那一段去掉，这种修改会给我们带来不必要的烦恼。
   */
  let CreateDiv = function (html) {
    if(instance) {
      return instance
    }
    this.html = html;
    this.init();
    return instance = this
  };
  CreateDiv.prototype.init = function () {
    let div = document.createElement('div');
    div.innerHTML = this.html;
    document.body.append(div);
  };
  return CreateDiv
};

// 代理单例
const CreateSection = function (html) {
  this.html = html;
  this.init()
};
CreateSection.prototype.init = function () {
  let div = document.createElement('div');
  div.innerHTML = this.html;
  document.body.append(div)
};
const proxySingletonCreateSection = (function () {
  let instance;

  return function (html) {
    return instance || (instance = new CreateSection(html))
  }
})();

// 通用的单例
const getSingle = function (fn) {
  let instance;
  return function () {
    return instance || (instance = fn.apply(this, arguments))
  }
};

const createLoginLayer = function () {
  let div = document.createElement('div');
  div.innerHTML = '哈哈哈';
  div.style.display = 'none';
  document.body.append(div);

  return div
};

let createSingleLoginLayer = getSingle(createLoginLayer);
